<template>
  <scroll-view
    v-if="pageData && pageData.length && total"
    :scroll-x="false"
    :scroll-y="true"
    :show-scrollbar="false"
    :refresher-enabled="true"
    @refresherrefresh="handlePrePage"
    :refresher-triggered="triggered"
    refresher-background="transparent"
    refresher-default-style="none"
    @scrolltolower="handlerScrollLower"
    :scroll-anchoring="true"
  >
    <template #refresher>
      <view class="scroll-loading-box">
        <uni-load-more status="loading" icon-type="circle" :show-text="false" color="#0030F9" />
      </view>
    </template>
    <view class="virtual-table__body">
      <slot></slot>
    </view>
    <view v-if="showLoadMore">
      <uni-load-more iconType="circle" :status="loadMoreStatus" />
    </view>
  </scroll-view>
  <not-data v-else btn-text="刷 新" @not-data-fn="getData"></not-data>
</template>

<script setup lang="ts">
import NotData from "@/components/error/NotData/index.vue";

defineOptions({ name: 'VirtualTable' })
import { UniLoadMoreStatus } from "@uni-helper/uni-types";

enum LoadMore {
  MORE = 'more',
  LOADING = 'loading',
  NO_MORE = 'noMore',
}

const props = defineProps({
  pageNo: {
    type: Number,
    default: 1,
  },
  pageSize: {
    type: Number,
    default: 10,
  },
  total: {
    type: Number,
    default: 0,
  },
  handlerGetList: {
    type: Function,
    default: () => {},
  },
  pageData: {
    type: Array<VirtualTableData>,
    default: () => [],
  }
})

const maxPageNo = computed(() => {
  return Math.ceil(props.total / props.pageSize);
})

const triggered = ref<boolean>(false);
const loadMoreStatus = ref<UniLoadMoreStatus>(LoadMore.MORE);
const showLoadMore = ref<boolean>(false);

const $emit = defineEmits(['update:pageNo', 'update:pageData']);

// 虚拟列表滚动至底部处理（下一页处理）
function handlerScrollLower() {
  showLoadMore.value = true
  let oldPageNo = props.pageNo;
  if (props.pageData && props.pageData.length) {
    oldPageNo = props.pageData[props.pageData.length - 1].pageNo;
  }
  if (oldPageNo + 1 > maxPageNo.value) {
    loadMoreStatus.value = LoadMore.NO_MORE;
  } else {
    $emit('update:pageNo', oldPageNo + 1);
    loadMoreStatus.value = LoadMore.LOADING;
    props.handlerGetList().then((res: any[]) => {
      if (res) {
        handlerUpdateData(props.pageNo, res, true);
      }
    }).finally(() => {
      loadMoreStatus.value = LoadMore.MORE;
    })
  }
}

// 虚拟列表滚动顶部处理（上一页处理）
function handlePrePage() {
  triggered.value = true;
  let newPage = 1;
  if (props.pageData && props.pageData.length) {
    const oldPageNo = props.pageData[0].pageNo
    newPage = oldPageNo - 1 < 1 ? 1 : oldPageNo - 1;
  }
  $emit('update:pageNo', newPage)
  if (props.handlerGetList) {
    if (props.pageNo === 1) {
      $emit('update:pageData', []);
    }
    props.handlerGetList().then((res: any[]) => {
      handlerUpdateData(props.pageNo, res, false);
    }).finally(() => {
      triggered.value = false;
    })
  } else {
    triggered.value = false;
  }
}

function handlerUpdateData(pageNo: number, list: any[], nextPage: boolean = false) {
  let newList =  markRaw([...props.pageData]);
  const pageList = newList.find((item) => item.pageNo === pageNo);
  if (pageList) {
    pageList.list = list;
  } else {
    newList.push({pageNo, list });
    newList = newList.sort((a, b) => a.pageNo - b.pageNo);
  }
  // 直接列表
  $emit('update:pageData', newList);

  // 虚拟列表
  // if (nextPage) {
  //   $emit('update:pageData', newList.slice(newList.length - 2, newList.length));
  // } else {
  //   $emit('update:pageData', newList.slice(0, 2));
  // }
}

function getData() {
  props.handlerGetList().then((res: any[]) => {
    handlerUpdateData(props.pageNo, res);
  })
}

onLoad(() => {
  getData()
})

defineExpose({
  getData,
  handlerUpdateData
})
</script>

<style scoped lang="scss">
.scroll-loading-box {
  width: 80rpx;
  height: 80rpx;
  border-radius: 50%;
  background-color: #fff;
  margin: 0 auto;
  box-shadow: 0px 0px 12px rgba(0, 0, 0, .12);
}
</style>
